﻿#include <stdlib.h>
#include <string.h>

#include "pch.h"
#include "framework.h"
#include "kmlInfoList.h"
#include "kmlInfoListDlg.h"
#include "afxdialogex.h"
#include "kmlInfo.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

int m_Row, m_Col;

// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_ABOUTBOX };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()

};

CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}


void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}



BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
	
END_MESSAGE_MAP()


// CkmlInfoListDlg 对话框



CkmlInfoListDlg::CkmlInfoListDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_KMLINFOLIST_DIALOG, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CkmlInfoListDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_LIST2, DataList);
}

BEGIN_MESSAGE_MAP(CkmlInfoListDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_CHOOSE_FILE_BUTTON, &CkmlInfoListDlg::OnBnClickedChooseFileButton)
	ON_BN_CLICKED(IDC_REFRESH_BUTTON, &CkmlInfoListDlg::OnBnClickedRefreshFileButton)
	ON_WM_DROPFILES()
	ON_WM_CONTEXTMENU()
	ON_NOTIFY(NM_DBLCLK, IDC_LIST2, &CkmlInfoListDlg::OnNMDblclkList2)
	ON_EN_KILLFOCUS(IDC_EDIT1, &CkmlInfoListDlg::OnEnKillfocusEdit1)
END_MESSAGE_MAP()


// CkmlInfoListDlg 消息处理程序

void CkmlInfoListDlg::FreeDataItems() {

	for (auto& item : dataItems) {
		free(item.layerName);
		free(item.name);
		free(item.description);
	}
	dataItems.clear();
}

BOOL CkmlInfoListDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != nullptr)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST2);
	// 确保ListView处于Report模式
	pListCtrl->SetView(LV_VIEW_DETAILS);

	pListCtrl->SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);

	// 获取ListView控件的客户区尺寸
	CRect rect;
	pListCtrl->GetClientRect(&rect);
	
	int totalWidth = rect.Width();

	int colNameWidth = 180;
	int colDescWidth = 0;
	int colXWidth = 100;
	int colYWidth = 100;
	int colZWidth = 80;
	int colLayerNameWidth = totalWidth - colNameWidth - colDescWidth - colXWidth - colYWidth - colZWidth;

	pListCtrl->InsertColumn(0, _T("图层名称"), LVCFMT_LEFT, colLayerNameWidth); // 列索引，列标题，对齐方式，列宽
	pListCtrl->InsertColumn(1, _T("要素名称"), LVCFMT_LEFT, colNameWidth);
	pListCtrl->InsertColumn(2, _T("X"), LVCFMT_LEFT, colXWidth);
	pListCtrl->InsertColumn(3, _T("Y"), LVCFMT_LEFT, colYWidth);
	pListCtrl->InsertColumn(4, _T("Z"), LVCFMT_LEFT, colZWidth);


	// 设置此对话框的图标。  当应用程序主窗口不是对话框时，框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	// 
	// 启用拖放文件支持
	DragAcceptFiles(TRUE);

	return TRUE;  // 除非将焦点设置到控件，否则返回 TRUE
}

void CkmlInfoListDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout; 
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮，则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序，
//  这将由框架自动完成。

void CkmlInfoListDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;


		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

void CkmlInfoListDlg::OnDestroy()
{
	// 释放所有动态分配的内存
	FreeDataItems();

	CDialogEx::OnDestroy();
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CkmlInfoListDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

void CkmlInfoListDlg::OnBnClickedChooseFileButton()
{
	// 设置过滤器   
	TCHAR szFilter[] = _T("KML文件|*.kml;*.ovkml|所有文件|*.*||");
	// 构造打开文件对话框   
	CFileDialog fileDlg(TRUE, NULL, NULL, 0, szFilter, this);
	CString strFilePath;

	// 显示打开文件对话框   
	if (IDOK == fileDlg.DoModal())
	{
		strFilePath = fileDlg.GetPathName();
		SetDlgItemText(IDC_EDIT_FILE_PATH, strFilePath);

		CString strLayerName;
		CString strFeatureName;
		GetDlgItemText(IDC_EDIT_LAYER_NAME, strLayerName);
		GetDlgItemText(IDC_EDIT_FEATURE_NAME, strFeatureName);

		char* filePath;
		char* layerName = nullptr;
		char* featureName = nullptr;

		// 使用 wcstombs_s 替代 wcstombs，并忽略错误检查

		char temp[100];
		::wsprintfA(temp, "%ls", (LPCTSTR)strFilePath);
		filePath = temp;

		if (!strLayerName.IsEmpty()) {
			::wsprintfA(temp, "%ls", (LPCTSTR)strLayerName);
			layerName = temp;
		}

		if (!strFeatureName.IsEmpty()) {
			::wsprintfA(temp, "%ls", (LPCTSTR)strFeatureName);
			featureName = temp;
		}

		GetDataList(filePath, layerName, featureName);

		FillListView();
	}

}

void CkmlInfoListDlg::OnBnClickedRefreshFileButton() {
	CString strFilePath;
	GetDlgItemText(IDC_EDIT_FILE_PATH, strFilePath);

	CString strLayerName;
	CString strFeatureName;
	GetDlgItemText(IDC_EDIT_LAYER_NAME, strLayerName);
	GetDlgItemText(IDC_EDIT_FEATURE_NAME, strFeatureName);

	char* filePath = nullptr;
	char* layerName = nullptr;
	char* featureName = nullptr;

	// 使用 wcstombs_s 替代 wcstombs，并忽略错误检查

	char filePathTemp[256];
	::wsprintfA(filePathTemp, "%ls", (LPCTSTR)strFilePath);
	filePath = filePathTemp;

	if (!strLayerName.IsEmpty()) {
		char strLayerNameTemp[256];
		::wsprintfA(strLayerNameTemp, "%ls", (LPCTSTR)strLayerName);
		layerName = strLayerNameTemp;
	}

	if (!strFeatureName.IsEmpty()) {
		char strFeatureNameTemp[256];
		::wsprintfA(strFeatureNameTemp, "%ls", (LPCTSTR)strFeatureName);
		featureName = strFeatureNameTemp;
	}

	GetDataList(filePath, layerName, featureName);

	FillListView();



}

void CkmlInfoListDlg:: FillListView()
{
	CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST2);

	// 清空现有条目
	pListCtrl->DeleteAllItems();

	for (size_t i = 0; i < dataItems.size(); ++i) {
		int nItem = pListCtrl->InsertItem(static_cast<int>(i), CString(dataItems[i].layerName));
		pListCtrl->SetItemText(nItem, 1, CString(dataItems[i].name));
		//pListCtrl->SetItemText(nItem, 2, CString(dataItems[i].description));

		// 将x、y、z坐标转换为字符串并设置到对应的列
		TCHAR buffer[50];
		_stprintf_s(buffer, _T("%.6f"), dataItems[i].x);
		pListCtrl->SetItemText(nItem, 2, buffer);

		_stprintf_s(buffer, _T("%.6f"), dataItems[i].y);
		pListCtrl->SetItemText(nItem, 3, buffer);

		_stprintf_s(buffer, _T("%.1f"), dataItems[i].z);
		pListCtrl->SetItemText(nItem, 4, buffer);
	}

}

void CkmlInfoListDlg::OnDropFiles(HDROP hDropInfo)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	//获取文件路径
	TCHAR szPath[MAX_PATH] = { 0 };
	DragQueryFile(hDropInfo, 0, szPath, MAX_PATH);
	//显示到控件上
	SetDlgItemText(IDC_EDIT_FILE_PATH, szPath);

	DragFinish(hDropInfo); // 完成拖放操作后必须调用此函数释放资源

	CDialogEx::OnDropFiles(hDropInfo);
}

void CkmlInfoListDlg::OnNMDblclkList2(NMHDR* pNMHDR, LRESULT* pResult)
{
	LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
	NMLISTVIEW* pNMListView = (NMLISTVIEW*)pNMHDR;

	// 获取选中的行和列
	 m_Row = pNMListView->iItem; // 获得选中的行
	 m_Col = pNMListView->iSubItem; // 获得选中列

	if (m_Row == -1 || m_Col == 0) // 如果没有选择行或选择了第一列（假设不允许编辑）
	{
		*pResult = 0;
		return;
	}

	CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST2);

	// 创建编辑框（如果尚未创建）
	static CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT1);

	// 获取子项的RECT
	CRect rc;
	pListCtrl->GetSubItemRect(m_Row, m_Col, LVIR_LABEL, rc);

	// 设置编辑框的父窗口为列表控件
	pEdit->SetParent(pListCtrl);

	// 将编辑框移动到列表控件的单元格位置
	pEdit->MoveWindow(rc);

	// 设置编辑框的内容为当前单元格的内容
	pEdit->SetWindowText(pListCtrl->GetItemText(m_Row, m_Col)); // 将该子项中的值放在Edit控件中
	pEdit->SetSel(0, -1); // 全选文本以便于立即编辑
	pEdit->ShowWindow(SW_SHOW); // 显示Edit控件
	pEdit->SetFocus(); // 设置Edit焦点
	pEdit->ShowCaret(); // 显示光标

	*pResult = 0;
}


void CkmlInfoListDlg::OnEnKillfocusEdit1()
{
	CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST2);

	// 创建编辑框（如果尚未创建）
	static CEdit* pEdit = (CEdit*)GetDlgItem(IDC_EDIT1);

	CString tem;
	pEdit->GetWindowText(tem);    //得到用户输入的新的内容
	pListCtrl->SetItemText(m_Row, m_Col, tem);   //设置编辑框的新内容
	pEdit->ShowWindow(SW_HIDE);                //隐藏编辑框

}

BOOL CkmlInfoListDlg::PreTranslateMessage(MSG* pMsg)
{
	if (pMsg->message == WM_KEYDOWN && pMsg->wParam == 'C' && (GetKeyState(VK_CONTROL) & 0x8000))
	{
		CopySelectedItem();
		return TRUE; // 消息已处理
	}
	return CDialogEx::PreTranslateMessage(pMsg);
}

void CkmlInfoListDlg::CopySelectedItem()
{
	CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST2);
	POSITION pos = pListCtrl->GetFirstSelectedItemPosition();

	if (pos == NULL)
	{
		AfxMessageBox(_T("请先选择要复制的行！"));
		return;
	}

	CString strText;

	while (pos != NULL)
	{
		int nItem = pListCtrl->GetNextSelectedItem(pos);

		// 遍历当前行的所有列
		for (int i = 0; i < pListCtrl->GetHeaderCtrl()->GetItemCount(); ++i)
		{
			CString itemText = pListCtrl->GetItemText(nItem, i);
			if (i > 0)
				strText += _T("\t"); // 使用制表符分隔列
			strText += itemText;
		}
		strText += _T("\n"); // 使用换行符分隔行
	}

	// 将CString转换为ANSI编码的字符串
	USES_CONVERSION;
	char* ansiStr = T2A(strText); // T2A宏用于将TCHAR字符串转换为ANSI字符串

	if (OpenClipboard())
	{
		EmptyClipboard();
		HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, strlen(ansiStr) + 1);
		memcpy(GlobalLock(hGlobal), ansiStr, strlen(ansiStr) + 1);
		GlobalUnlock(hGlobal);
		SetClipboardData(CF_TEXT, hGlobal);
		CloseClipboard();
	}
}